package com.ct.util;


import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;

import java.util.HashMap;
import java.util.Map;

public class BusUtil {

    private static final String[] CN_REGS = {"：", "，", "；", "-","（","）"};
    private static final String[] EN_REGS = {":", ",", ";", "-","(",")"};

    public static String replaceRegs(String str) {
        if (StrUtil.isNotBlank(str)) {
            for (int i = 0; i < CN_REGS.length; i++) {
                str = str.replaceAll(CN_REGS[i], EN_REGS[i]);
            }
        }
        return str;
    }

    public static Map<String, String> convertMap(Map<String, Object> params) {
        Map<String, String> tmpMap = new HashMap<>();
        for (String key : params.keySet()) {
            Object value = params.get(key);
            if (value instanceof JSONObject || (value != null && value.getClass().isArray())) {
                tmpMap.put(key, JSON.toJSONString(value));
            } else {
                tmpMap.put(key, String.valueOf(value));
            }
        }

        return tmpMap;
    }

    /**
     * make a int with bytes in big endian (max 4 bytes because int is 32-bit in java)
     * example: {0x12, 0x34 , 0x56} - 0x00123456
     *
     * @param bts bytes array
     * @return int            value
     * @throws Exception when input is null or error length.
     */
    public static int bytesToInt(byte[] bts) throws Exception {

        return bytesToInt(bts, 0, bts.length);
    }

    /**
     * make a int with bytes in big endian (max 4 bytes because int is 32-bit in java)
     * example: {0x12, 0x34 , 0x56} - 0x00123456
     *
     * @param bts     bytes array
     * @param iOff    offset in bytes array
     * @param iExpLen len in bytes array
     * @return int            value
     * @throws Exception when input is null or error length.
     */
    public static int bytesToInt(byte[] bts, int iOff, int iExpLen) {

        if (iExpLen > 4) {
            throw new Error("unsupport bytes array length");
        }

        int iTmp = 0;
        for (int i = 0; i < iExpLen; i++) {
            iTmp = iTmp << 8;
            iTmp = iTmp | (bts[iOff++] & 0x00FF);
        }

        return iTmp;
    }

    /**
     * make a byte array with int in big endian
     * example 0xFFFF1234 - {0xFF,0xFF,0x12,0x34}
     *
     * @param iValue
     * @param iExpLen
     * @return
     */
    public static byte[] intToBytes(int iValue, int iExpLen) {

        byte[] bts = new byte[iExpLen];

        intToBytes(iValue, iExpLen, bts, 0);

        return bts;
    }

    /**
     * make a byte array with int in big endian
     * example 0xFFFF1234 - {0xFF,0xFF,0x12,0x34}
     *
     * @param iValue  IN	value
     * @param iExpLen length of bytes
     * @param buf     OUT byte array
     * @param iOff    byte array off
     * @return length of bytes
     */
    public static int intToBytes(int iValue, int iExpLen, byte[] buf, int iOff) {

        for (int iLen = iExpLen; iLen > 0; iLen--) {
            int iTmp = iValue;
            for (int i = 0; i < (iLen - 1); i++) {
                iTmp = iTmp >> 8;
            }
            buf[iOff++] = (byte) (iTmp & 0xFF);
        }
        return iExpLen;
    }

    /**
     * transmit a Hex-byte to Hex-character in upper case
     * example: (0x0a - 'A')
     *
     * @param b Hex-byte(0x00-0x0F)
     * @return char        Hex-character: '0' - '9', 'A' - 'F'
     */
    public static char byteToHexChar(byte b) {
        if (b > 0x0F) {
            throw new Error("Not a Hex Byte: " + b);
        }

        if ((b >= 0) && (b <= 9)) {
            return (char) (b + '0');
        } else {
            return (char) ((b - 0x0A) + 'A');
        }
    }

    /**
     * transmit a hex-bytes array to a hex-charater string
     * example:({0x1A,0x02} - "1A02"
     *
     * @param bts Hex-byte array
     * @return String        Hex-string build by Hex-characters
     * @throws Exception when input is not build by hex-bytes
     */
    public static String bytesToString(byte[] bts) {
        return bytesToString(bts, 0, bts.length);
    }

    /**
     * transmit a hex-bytes array to a hex-charater string
     * example:({0x1A,0x02} - "1A02"
     *
     * @param bts
     * @param off
     * @param length
     * @return
     */
    public static String bytesToString(byte[] bts, int off, int length) {
        StringBuffer str = new StringBuffer(length * 2);
        for (int i = 0; i < length; i++) {
            str.append(byteToHexChar((byte) ((bts[i + off] >> 4) & 0x0F)));
            str.append(byteToHexChar((byte) (bts[i + off] & 0x0F)));
        }

        return str.toString();
    }

    /**
     * transmit a Hex-character to a Hex-byte
     * example:('A' - 0x0a)
     *
     * @param c Hex-character: '0' - '9', 'A' - 'F', 'a' - 'f'
     * @return byte        Hex-byte: 0x00 - 0x0F
     */
    public static byte hexCharToByte(char c) {
        if ((c >= 'a') && (c <= 'f')) {
            return (byte) (0x0A + (c - 'a'));
        }

        if ((c >= 'A') && (c <= 'F')) {
            return (byte) (0x0A + (c - 'A'));
        }

        if ((c >= '0') && (c <= '9')) {
            return (byte) (0x00 + (c - '0'));
        }

        throw new Error("unsupport charset: " + c);

    }

    /**
     * transmit a hex-character string to byte array
     * example:("1A02" - {0x1A,0x02}
     *
     * @param str Hex-string build by Hex-characters
     * @return byte[]        Hex-byte array
     */
    public static byte[] stringToBytes(String str) {
        if ((str.length() % 2) != 0) {
            throw new Error("Not a Hex String: " + str);
        }

        byte[] ret = new byte[str.length() / 2];

        for (int i = 0; i < ret.length; i++) {
            ret[i] = hexCharToByte(str.charAt(i * 2));
            ret[i] = (byte) (ret[i] << 4);
            ret[i] |= hexCharToByte(str.charAt(i * 2 + 1));
        }
        return ret;
    }

    /**
     * ECC/SM2 公钥压缩
     *
     * @param pk64 64字节公钥
     * @return 压缩后的33字节公钥
     */
    public static byte[] compress(byte[] pk64) {
        byte[] pk33 = new byte[33];
        for (int i = 0; i < 32; ++i) {
            pk33[i + 1] = pk64[i];
        }
        pk33[0] = (byte) (2 + (pk64[32 * 2 - 1] & 0x01));
        return pk33;
    }

}
